package  
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import org.flixel.*;
	
	/**
	 * Entity is any interactable object on the map that isn't the map.
	 * @author morgan
	 */
	public class Entity extends FlxSprite 
	{
		protected var mapMask:FlxSprite;
		
		public var leftLine:BitmapData;
		public var rightLine:BitmapData;
		public var topLine:BitmapData;
		public var bottomLine:BitmapData;
		
		public var atRestPoint:FlxPoint = new FlxPoint(0, 0);
		public var atRest:Boolean = false;
		
		public var targeted:Boolean = false;
		public var bugInfluence:Number = 0;
		public var requiredInfluence:Number = 100;
		
		public function Entity(x:int, y:int, map:FlxSprite) 
		{
			super(x, y);
			mapMask = map;
		}
		
		override public function update():void 
		{
			super.update();
			if (atRest)
			{
				x = atRestPoint.x;
				y = atRestPoint.y;
			}
			updateCarrying();
			updateCollision();
		}
		
		public function updateCarrying():void
		{	
			var state:GameState = (FlxG.state as GameState);
			
			if (pixelsOverlapPoint(new FlxPoint(FlxG.mouse.x, FlxG.mouse.y), 0x00000000) && FlxG.mouse.justPressed())
			{
				state.bugTargetObj = this;
			}
			
			var targeted:Boolean = state.bugTargetObj == this;
			
			if (FlxG.mouse.justReleased())
			{
				state.bugTargetObj = null;
			}
			
			var g:uint = 255 - Math.min((bugInfluence / requiredInfluence) * 255, 255);
			var b:uint = 255 - Math.min((bugInfluence / requiredInfluence) * 255, 255);
			color = 0xffff0000 + 0x00000100 * g + 0x00000001 * b;
			
			if (bugInfluence >= requiredInfluence && targeted)
			{
				color = 0xff00ff00;
				var extraBugs:Number = bugInfluence - requiredInfluence;
				var offx:Number = FlxG.mouse.x - (x + width/2);
				var offy:Number = FlxG.mouse.y - (y + height / 2);
				var d:Number = Math.sqrt(offx * offx + offy * offy);
				offx /= d;
				offy /= d;
				var speed:Number = Math.min((15 + 400.0 / requiredInfluence), 50);
				velocity.x = offx * speed;
				velocity.y = offy * speed;
				if (atRest)
				{
					x += offx;
					y += offy;
					atRest = false;
				}
			}
			
			bugInfluence *= 0.75;
		}
		
		public function updateCollision():void
		{
			if (FlxCollision.pixelPerfectCheck(this, mapMask))
			{
				// FlxCollision.debug is an image which shows the overlapping parts of the two images.
				var h:uint = FlxCollision.debug.height;
				var w:uint = FlxCollision.debug.width;
				
				var overlap:Rectangle = FlxCollision.debug.getColorBoundsRect(0xffffffff, 0xff00ffff, true);
				
				// We construct 4, like, sensors. One per direction. They're just the collision image cropped to each
				// edge of the rectangle.
				
				leftLine = new BitmapData(w/2, h);
				rightLine = new BitmapData(w/2, h);
				topLine = new BitmapData(w, h/2);
				bottomLine = new BitmapData(w, h/2);
				
				leftLine.copyPixels(FlxCollision.debug, new Rectangle(0, 1, 8, h-2), new Point(0, 0), FlxCollision.debug, new Point(0, 0));
				rightLine.copyPixels(FlxCollision.debug, new Rectangle(w - 8, 1, 8, h-2), new Point(0, 0), FlxCollision.debug, new Point(w/2, 0));
				topLine.copyPixels(FlxCollision.debug, new Rectangle(1, 0, w-2, 8), new Point(0, 0), FlxCollision.debug, new Point(0, 0));
				bottomLine.copyPixels(FlxCollision.debug, new Rectangle(1, h-8, w-2, 8), new Point(0, 0), FlxCollision.debug, new Point(0, h/2));
				
				// Figure out which sides have collision pixels in them
				var dl:Boolean = !leftLine.getColorBoundsRect(0xffffffff, 0xff00ffff, true).isEmpty()
				var dr:Boolean = !rightLine.getColorBoundsRect(0xffffffff, 0xff00ffff, true).isEmpty()
				var dt:Boolean = !topLine.getColorBoundsRect(0xffffffff, 0xff00ffff, true).isEmpty()
				var db:Boolean = !bottomLine.getColorBoundsRect(0xffffffff, 0xff00ffff, true).isEmpty()
				
				// Left collision and no right collision
				if (dl && !dr)
				{
					velocity.x = Math.abs(velocity.x) * 0.5;
				}
				// vice-versa
				else if (dr && !dl)
				{
					velocity.x = -Math.abs(velocity.x) * 0.5;
				}
				// Top collision and no bottom collision
				if (dt && !db)
				{
					velocity.y = Math.abs(velocity.y) * 0.5;
				}
				// Vice-verse
				else if (db && !dt)
				{
					velocity.y = -Math.abs(velocity.y) * 0.5;
				}
				// Objects stop moving if they are slow. 
				if (Math.abs(velocity.y) <= 10 && Math.abs(velocity.x) <= 10)
				{
					if (!((FlxG.state as GameState).bugTargetObj == this))
					{
						atRestPoint = new FlxPoint(x, y);
						atRest = true;
					}
				}
			}
		}
	}
}